package top.lingkang.mm.page;

import cn.hutool.core.convert.BasicType;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import top.lingkang.mm.orm.BaseQuery;
import top.lingkang.mm.orm.Query;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 分页实现。默认是mysql的分页实现。
 *
 * @author lingkang
 * Created by 2024/3/3
 */
public interface PageSqlHandle {
    Pattern orderBy = Pattern.compile("order\\s+by");

    /**
     * 处理分页sql, 下面默认是mysql分页逻辑
     *
     * @param selectSql 查询的原sql
     * @param page      最小值 1
     * @param size      最小值 1
     */
    default PageSqlInfo handleSql(String selectSql, int page, int size) {
        String sql = selectSql.toLowerCase();

        int index = sql.indexOf("from");
        int start = sql.substring(0, index).indexOf("(");
        while (start != -1) {
            start = sql.indexOf("(", start + 1);
            if (start == -1)
                index = sql.indexOf("from", index + 1);
        }

        // 匹配排序，可能存在排序，需要特殊处理
        Matcher matcher = orderBy.matcher(sql);
        PageSqlInfo info = new PageSqlInfo();
        if (matcher.find())
            info.setCountSql("select count(*) " + selectSql.substring(index, matcher.start()));
        else
            info.setCountSql("select count(*) " + selectSql.substring(index));

        info.setSelectSql(selectSql + " limit " + (page - 1) * size + "," + size);
        return info;
    }

    default void handleParams(BoundSql boundSql, PreparedStatement statement) throws Throwable {
        if (boundSql.getParameterObject() != null) {
            Object parameterObject = boundSql.getParameterObject();
            if (parameterObject.getClass().isPrimitive() || BasicType.WRAPPER_PRIMITIVE_MAP.containsKey(parameterObject.getClass())) {
                statement.setObject(1, parameterObject);
            } else if (parameterObject.getClass().isArray()) {
                Object[] arr = (Object[]) parameterObject;
                for (int i = 1; i <= arr.length; i++)
                    statement.setObject(i, arr[i]);
            } else if (parameterObject instanceof Collection) {
                int i = 1;
                for (Object o : (Collection) parameterObject)
                    statement.setObject(i++, o);
            } else if (parameterObject instanceof Map) {
                Map map = (Map) parameterObject;
                int i = 1;
                for (ParameterMapping mapping : boundSql.getParameterMappings()) {
                    String name = mapping.getProperty();
                    if (name.contains(".")){
                        String[] split = name.split("\\.");
                        BaseQuery query= (BaseQuery) map.get(split[0]);
                        statement.setObject(i++, query.getParam().get(split[2]));
                    } else
                        statement.setObject(i++, map.get(name));
                }
            } else {
                // 将它当成对象
                int i = 1;
                for (ParameterMapping mapping : boundSql.getParameterMappings()) {
                    Field field = parameterObject.getClass().getDeclaredField(mapping.getProperty());
                    field.setAccessible(true);
                    statement.setObject(i++, field.get(parameterObject));
                }
            }
        }
    }
}
